package utils

import (
	"context"
	"fmt"
	"gogogo/controllers"
	"gogogo/helpers"
	"gogogo/memory"
	"gogogo/models"
	"log"
	"math/rand"
	"net/http"
	"os"
	"os/signal"
	"runtime"
	"syscall"
	"time"

	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/fiber/v2/middleware/cors"
	"github.com/gofiber/fiber/v2/middleware/recover"
	"github.com/robfig/cron/v3"

	jwtware "github.com/gofiber/jwt/v3"
)

// get the exit signal and handle last
func gracefulExitWeb(server *http.Server) {
	ch := make(chan os.Signal)
	signal.Notify(ch, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT)
	sig := <-ch

	fmt.Println("got a signal", sig)
	now := time.Now()
	cxt, cancel := context.WithTimeout(context.Background(), 3*time.Second)
	defer cancel()
	err := server.Shutdown(cxt)
	if err != nil {
		fmt.Println("err", err)
	}

	// 实际退出所耗费的时间
	fmt.Println("------exited--------", time.Since(now))
}

var c *cron.Cron

func Setup() {
	// 0.设置随机种子
	rand.Seed(time.Now().UnixNano())
	// 1.12默认有这个不用写了
	runtime.GOMAXPROCS(runtime.NumCPU())
	// 1.读取配置文件(本地)
	// 1.x 从配置中心读取配置
	helpers.GetCfgInstance().Load("config", ".")
	// 2.设置日志
	// 2.设置日志中心
	helpers.GetLoggerInstance().InitLogger("./all.log", "info")

	// 3.init database Instance
	models.GetInstance().Connect(helpers.GetCfgInstance().Conf.DbDsn, helpers.GetCfgInstance().Conf.PoolIdle, helpers.GetCfgInstance().Conf.PoolMax)
	// 3.1 读取字典表
	models.GetInstance().LoadCommonConfigToMemory()
	// 3.2 初始化REDIS
	memory.GetInstance().Connect(helpers.GetCfgInstance().Conf.RedisCfg, 0)

	// 4.初始化定时任务
	c = controllers.SetupAndGo()

	// 5.初始化服务器
	// 静态文件
	app := fiber.New()
	// 错误处理
	app.Use(recover.New())
	// 跨域配置
	app.Use(cors.New(cors.Config{Next: nil,
		AllowOrigins:     "*",
		AllowMethods:     "GET,POST,HEAD,PUT,DELETE,PATCH,OPTIONS",
		AllowHeaders:     "",
		AllowCredentials: false,
		ExposeHeaders:    "",
		MaxAge:           0}))
	app.Static("/", "./uploads")
	// 不用jwt的路由
	controllers.InitRouteTables(app)
	// JWT Middleware
	app.Use(jwtware.New(jwtware.Config{
		SigningKey: []byte(helpers.GetCfgInstance().Conf.Jwt),
	}))
	// 需要jwt的路由
	controllers.InitRouteTablesWithJWT(app)

	log.Fatal(app.Listen(fmt.Sprintf(":%d", helpers.GetCfgInstance().Conf.Port)))

	controllers.StopAndClean(c)
}
